package main

import (
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis/v8"
	"github.com/spf13/viper"
	"math/rand"
	"strconv"
	"time"
)

// generate at https://github.com/ozh/github-colors/blob/master/colors.json
var colors = map[string]string{"1C Enterprise": "#814CCC", "2-Dimensional Array": "#38761D", "4D": "#004289", "ABAP": "#E8274B", "ABAP CDS": "#555e25", "ActionScript": "#882B0F", "Ada": "#02f88c", "Adblock Filter List": "#800000", "Adobe Font Metrics": "#fa0f00", "Agda": "#315665", "AGS Script": "#B9D9FF", "AIDL": "#34EB6B", "AL": "#3AA2B5", "Alloy": "#64C800", "Alpine Abuild": "#0D597F", "Altium Designer": "#A89663", "AMPL": "#E6EFBB", "AngelScript": "#C7D7DC", "Ant Build System": "#A9157E", "Antlers": "#ff269e", "ANTLR": "#9DC3FF", "ApacheConf": "#d12127", "Apex": "#1797c0", "API Blueprint": "#2ACCA8", "APL": "#5A8164", "Apollo Guidance Computer": "#0B3D91", "AppleScript": "#101F1F", "Arc": "#aa2afe", "AsciiDoc": "#73a0c5", "ASL": "#d2cece", "ASP.NET": "#9400ff", "AspectJ": "#a957b0", "Assembly": "#6E4C13", "Astro": "#ff5a03", "Asymptote": "#ff0000", "ATS": "#1ac620", "Augeas": "#9CC134", "AutoHotkey": "#6594b9", "AutoIt": "#1C3552", "Avro IDL": "#0040FF", "Awk": "#c30e9b", "Ballerina": "#FF5000", "BASIC": "#ff0000", "Batchfile": "#C1F12E", "Beef": "#a52f4e", "Befunge": "#d2cece", "Berry": "#15A13C", "BibTeX": "#778899", "Bicep": "#519aba", "Bikeshed": "#5562ac", "Bison": "#6A463F", "BitBake": "#00bce4", "Blade": "#f7523f", "BlitzBasic": "#00FFAE", "BlitzMax": "#cd6400", "Bluespec": "#12223c", "Boo": "#d4bec1", "Boogie": "#c80fa0", "Brainfuck": "#2F2530", "BrighterScript": "#66AABB", "Brightscript": "#662D91", "Browserslist": "#ffd539", "C": "#555555", "C#": "#178600", "C++": "#f34b7d", "C2hs Haskell": "#d2cece", "Cabal Config": "#483465", "Cadence": "#00ef8b", "Cairo": "#ff4a48", "CameLIGO": "#3be133", "CAP CDS": "#0092d1", "Cap'n Proto": "#c42727", "CartoCSS": "#d2cece", "Ceylon": "#dfa535", "Chapel": "#8dc63f", "Charity": "#d2cece", "ChucK": "#3f8000", "Circom": "#707575", "Cirru": "#ccccff", "Clarion": "#db901e", "Clarity": "#5546ff", "Classic ASP": "#6a40fd", "Clean": "#3F85AF", "Click": "#E4E6F3", "CLIPS": "#00A300", "Clojure": "#db5855", "Closure Templates": "#0d948f", "Cloud Firestore Security Rules": "#FFA000", "CMake": "#DA3434", "COBOL": "#d2cece", "CodeQL": "#140f46", "CoffeeScript": "#244776", "ColdFusion": "#ed2cd6", "ColdFusion CFC": "#ed2cd6", "COLLADA": "#F1A42B", "Common Lisp": "#3fb68b", "Common Workflow Language": "#B5314C", "Component Pascal": "#B0CE4E", "Cool": "#d2cece", "Coq": "#d0b68c", "Crystal": "#000100", "CSON": "#244776", "Csound": "#1a1a1a", "Csound Document": "#1a1a1a", "Csound Score": "#1a1a1a", "CSS": "#563d7c", "CSV": "#237346", "Cuda": "#3A4E3A", "CUE": "#5886E1", "Curry": "#531242", "CWeb": "#00007a", "Cycript": "#d2cece", "Cypher": "#34c0eb", "Cython": "#fedf5b", "D": "#ba595e", "Dafny": "#FFEC25", "Darcs Patch": "#8eff23", "Dart": "#00B4AB", "DataWeave": "#003a52", "Debian Package Control File": "#D70751", "DenizenScript": "#FBEE96", "Dhall": "#dfafff", "DIGITAL Command Language": "#d2cece", "DirectX 3D File": "#aace60", "DM": "#447265", "Dockerfile": "#384d54", "Dogescript": "#cca760", "Dotenv": "#e5d559", "DTrace": "#d2cece", "Dylan": "#6c616e", "E": "#ccce35", "Earthly": "#2af0ff", "Easybuild": "#069406", "eC": "#913960", "Ecere Projects": "#913960", "ECL": "#8a1267", "ECLiPSe": "#001d9d", "Ecmarkup": "#eb8131", "EditorConfig": "#fff1f2", "Eiffel": "#4d6977", "EJS": "#a91e50", "Elixir": "#6e4a7e", "Elm": "#60B5CC", "Elvish": "#55BB55", "Elvish Transcript": "#55BB55", "Emacs Lisp": "#c065db", "EmberScript": "#FFF4F3", "EQ": "#a78649", "Erlang": "#B83998", "Euphoria": "#FF790B", "F#": "#b845fc", "F*": "#572e30", "Factor": "#636746", "Fancy": "#7b9db4", "Fantom": "#14253c", "Faust": "#c37240", "Fennel": "#fff3d7", "FIGlet Font": "#FFDDBB", "Filebench WML": "#F6B900", "Filterscript": "#d2cece", "fish": "#4aae47", "Fluent": "#ffcc33", "FLUX": "#88ccff", "Forth": "#341708", "Fortran": "#4d41b1", "Fortran Free Form": "#4d41b1", "FreeBasic": "#141AC9", "FreeMarker": "#0050b2", "Frege": "#00cafe", "Futhark": "#5f021f", "G-code": "#D08CF2", "Game Maker Language": "#71b417", "GAML": "#FFC766", "GAMS": "#f49a22", "GAP": "#0000cc", "GCC Machine Description": "#FFCFAB", "GDB": "#d2cece", "GDScript": "#355570", "GEDCOM": "#003058", "Gemfile.lock": "#701516", "Gemini": "#ff6900", "Genero": "#63408e", "Genero Forms": "#d8df39", "Genie": "#fb855d", "Genshi": "#951531", "Gentoo Ebuild": "#9400ff", "Gentoo Eclass": "#9400ff", "Gerber Image": "#d20b00", "Gherkin": "#5B2063", "Git Attributes": "#F44D27", "Git Config": "#F44D27", "Git Revision List": "#F44D27", "Gleam": "#ffaff3", "GLSL": "#5686a5", "Glyph": "#c1ac7f", "Gnuplot": "#f0a9f0", "Go": "#00ADD8", "Go Checksums": "#00ADD8", "Go Module": "#00ADD8", "Godot Resource": "#355570", "Golo": "#88562A", "Gosu": "#82937f", "Grace": "#615f8b", "Gradle": "#02303a", "Grammatical Framework": "#ff0000", "GraphQL": "#e10098", "Graphviz (DOT)": "#2596be", "Groovy": "#4298b8", "Groovy Server Pages": "#4298b8", "GSC": "#FF6800", "Hack": "#878787", "Haml": "#ece2a9", "Handlebars": "#f7931e", "HAProxy": "#106da9", "Harbour": "#0e60e3", "Haskell": "#5e5086", "Haxe": "#df7900", "HCL": "#844FBA", "HiveQL": "#dce200", "HLSL": "#aace60", "HOCON": "#9ff8ee", "HolyC": "#ffefaf", "hoon": "#00b171", "HTML": "#e34c26", "HTML+ECR": "#2e1052", "HTML+EEX": "#6e4a7e", "HTML+ERB": "#701516", "HTML+PHP": "#4f5d95", "HTML+Razor": "#512be4", "HTTP": "#005C9C", "HXML": "#f68712", "Hy": "#7790B2", "HyPhy": "#d2cece", "IDL": "#a3522f", "Idris": "#b30000", "Ignore List": "#000000", "IGOR Pro": "#0000cc", "ImageJ Macro": "#99AAFF", "Imba": "#16cec6", "Inform 7": "#d2cece", "INI": "#d1dbe0", "Ink": "#d2cece", "Inno Setup": "#264b99", "Io": "#a9188d", "Ioke": "#078193", "Isabelle": "#FEFE00", "Isabelle ROOT": "#FEFE00", "J": "#9EEDFF", "Janet": "#0886a5", "JAR Manifest": "#b07219", "Jasmin": "#d03600", "Java": "#b07219", "Java Properties": "#2A6277", "Java Server Pages": "#2A6277", "JavaScript": "#f1e05a", "JavaScript+ERB": "#f1e05a", "JCL": "#d90e09", "Jest Snapshot": "#15c213", "JetBrains MPS": "#21D789", "JFlex": "#DBCA00", "Jinja": "#a52a22", "Jison": "#56b3cb", "Jison Lex": "#56b3cb", "Jolie": "#843179", "jq": "#c7254e", "JSON": "#292929", "JSON with Comments": "#292929", "JSON5": "#267CB9", "JSONiq": "#40d47e", "JSONLD": "#0c479c", "Jsonnet": "#0064bd", "Julia": "#a270ba", "Jupyter Notebook": "#DA5B0B", "Just": "#384d54", "Kaitai Struct": "#773b37", "KakouneScript": "#6f8042", "KerboScript": "#41adf0", "KiCad Layout": "#2f4aab", "KiCad Legacy Layout": "#2f4aab", "KiCad Schematic": "#2f4aab", "Kotlin": "#A97BFF", "KRL": "#28430A", "kvlang": "#1da6e0", "LabVIEW": "#fede06", "Lark": "#2980B9", "Lasso": "#999999", "Latte": "#f2a542", "Lean": "#d2cece", "Less": "#1d365d", "Lex": "#DBCA00", "LFE": "#4C3023", "LigoLANG": "#0e74ff", "LilyPond": "#9ccc7c", "Limbo": "#d2cece", "Liquid": "#67b8de", "Literate Agda": "#315665", "Literate CoffeeScript": "#244776", "Literate Haskell": "#5e5086", "LiveScript": "#499886", "LLVM": "#185619", "Logos": "#d2cece", "Logtalk": "#295b9a", "LOLCODE": "#cc9900", "LookML": "#652B81", "LoomScript": "#d2cece", "LSL": "#3d9970", "Lua": "#000080", "M": "#d2cece", "M4": "#d2cece", "M4Sugar": "#d2cece", "Macaulay2": "#d8ffff", "Makefile": "#427819", "Mako": "#7e858d", "Markdown": "#083fa1", "Marko": "#42bff2", "Mask": "#f97732", "Mathematica": "#dd1100", "MATLAB": "#e16737", "Max": "#c4a79c", "MAXScript": "#00a6a6", "mcfunction": "#E22837", "Mercury": "#ff2b2b", "Mermaid": "#ff3670", "Meson": "#007800", "Metal": "#8f14e9", "MiniD": "#d2cece", "MiniYAML": "#ff1111", "Mint": "#02b046", "Mirah": "#c7a938", "mIRC Script": "#3d57c3", "MLIR": "#5EC8DB", "Modelica": "#de1d31", "Modula-2": "#10253f", "Modula-3": "#223388", "Module Management System": "#d2cece", "Monkey": "#d2cece", "Monkey C": "#8D6747", "Moocode": "#d2cece", "MoonScript": "#ff4585", "Motoko": "#fbb03b", "Motorola 68K Assembly": "#005daa", "Move": "#4a137a", "MQL4": "#62A8D6", "MQL5": "#4A76B8", "MTML": "#b7e1f4", "MUF": "#d2cece", "mupad": "#244963", "Mustache": "#724b3b", "Myghty": "#d2cece", "nanorc": "#2d004d", "Nasal": "#1d2c4e", "NASL": "#d2cece", "NCL": "#28431f", "Nearley": "#990000", "Nemerle": "#3d3c6e", "nesC": "#94B0C7", "NetLinx": "#0aa0ff", "NetLinx+ERB": "#747faa", "NetLogo": "#ff6375", "NewLisp": "#87AED7", "Nextflow": "#3ac486", "Nginx": "#009639", "Nim": "#ffc200", "Nit": "#009917", "Nix": "#7e7eff", "NPM Config": "#cb3837", "NSIS": "#d2cece", "Nu": "#c9df40", "NumPy": "#9C8AF9", "Nunjucks": "#3d8137", "NWScript": "#111522", "OASv2-json": "#85ea2d", "OASv2-yaml": "#85ea2d", "OASv3-json": "#85ea2d", "OASv3-yaml": "#85ea2d", "Objective-C": "#438eff", "Objective-C++": "#6866fb", "Objective-J": "#ff0c5a", "ObjectScript": "#424893", "OCaml": "#3be133", "Odin": "#60AFFE", "Omgrofl": "#cabbff", "ooc": "#b0b77e", "Opa": "#d2cece", "Opal": "#f7ede0", "Open Policy Agent": "#7d9199", "OpenAPI Specification v2": "#85ea2d", "OpenAPI Specification v3": "#85ea2d", "OpenCL": "#ed2e2d", "OpenEdge ABL": "#5ce600", "OpenQASM": "#AA70FF", "OpenRC runscript": "#d2cece", "OpenSCAD": "#e5cd45", "Option List": "#476732", "Org": "#77aa99", "Ox": "#d2cece", "Oxygene": "#cdd0e3", "Oz": "#fab738", "P4": "#7055b5", "Pan": "#cc0000", "Papyrus": "#6600cc", "Parrot": "#f3ca0a", "Parrot Assembly": "#d2cece", "Parrot Internal Representation": "#d2cece", "Pascal": "#E3F171", "Pawn": "#dbb284", "PDDL": "#0d00ff", "PEG.js": "#234d6b", "Pep8": "#C76F5B", "Perl": "#0298c3", "PHP": "#4F5D95", "PicoLisp": "#6067af", "PigLatin": "#fcd7de", "Pike": "#005390", "PlantUML": "#fbbd16", "PLpgSQL": "#336790", "PLSQL": "#dad8d8", "PogoScript": "#d80074", "Polar": "#ae81ff", "Pony": "#d2cece", "Portugol": "#f8bd00", "PostCSS": "#dc3a0c", "PostScript": "#da291c", "POV-Ray SDL": "#6bac65", "PowerBuilder": "#8f0f8d", "PowerShell": "#012456", "Prisma": "#0c344b", "Processing": "#0096D8", "Procfile": "#3B2F63", "Prolog": "#74283c", "Promela": "#de0000", "Propeller Spin": "#7fa2a7", "Pug": "#a86454", "Puppet": "#302B6D", "PureBasic": "#5a6986", "PureScript": "#1D222D", "Pyret": "#ee1e10", "Python": "#3572A5", "Python console": "#3572A5", "Python traceback": "#3572A5", "q": "#0040cd", "Q#": "#fed659", "QMake": "#d2cece", "QML": "#44a51c", "Qt Script": "#00b841", "Quake": "#882233", "R": "#198CE7", "Racket": "#3c5caa", "Ragel": "#9d5200", "Raku": "#0000fb", "RAML": "#77d9fb", "Rascal": "#fffaa0", "RDoc": "#701516", "REALbasic": "#d2cece", "Reason": "#ff5847", "ReasonLIGO": "#ff5847", "Rebol": "#358a5b", "Record Jar": "#0673ba", "Red": "#f50000", "Redcode": "#d2cece", "Regular Expression": "#009a00", "Ren'Py": "#ff7f7f", "RenderScript": "#d2cece", "ReScript": "#ed5051", "reStructuredText": "#141414", "REXX": "#d90e09", "Ring": "#2D54CB", "Riot": "#A71E49", "RMarkdown": "#198ce7", "RobotFramework": "#00c0b5", "Roff": "#ecdebe", "Roff Manpage": "#ecdebe", "Rouge": "#cc0088", "RouterOS Script": "#DE3941", "RPC": "#d2cece", "RPGLE": "#2BDE21", "Ruby": "#701516", "RUNOFF": "#665a4e", "Rust": "#dea584", "Sage": "#d2cece", "SaltStack": "#646464", "SAS": "#B34936", "Sass": "#a53b70", "Scala": "#c22d40", "Scaml": "#bd181a", "Scenic": "#fdc700", "Scheme": "#1e4aec", "Scilab": "#ca0f21", "SCSS": "#c6538c", "sed": "#64b970", "Self": "#0579aa", "ShaderLab": "#222c37", "Shell": "#89e051", "ShellCheck Config": "#cecfcb", "ShellSession": "#d2cece", "Shen": "#120F14", "Sieve": "#d2cece", "Simple File Verification": "#C9BFED", "Singularity": "#64E6AD", "Slash": "#007eff", "Slice": "#003fa2", "Slim": "#2b2b2b", "Smali": "#d2cece", "Smalltalk": "#596706", "Smarty": "#f0c040", "Smithy": "#c44536", "SmPL": "#c94949", "SMT": "#d2cece", "Snakemake": "#419179", "Solidity": "#AA6746", "SourcePawn": "#f69e1d", "SPARQL": "#0C4597", "SQF": "#3F3F3F", "SQL": "#e38c00", "SQLPL": "#e38c00", "Squirrel": "#800000", "SRecode Template": "#348a34", "Stan": "#b2011d", "Standard ML": "#dc566d", "Starlark": "#76d275", "Stata": "#1a5f91", "STL": "#373b5e", "StringTemplate": "#3fb34f", "Stylus": "#ff6347", "SubRip Text": "#9e0101", "SugarSS": "#2fcc9f", "SuperCollider": "#46390b", "Svelte": "#ff3e00", "SVG": "#ff9900", "Sway": "#dea584", "Swift": "#F05138", "SWIG": "#d2cece", "SystemVerilog": "#DAE1C2", "Talon": "#333333", "Tcl": "#e4cc98", "Tcsh": "#d2cece", "Terra": "#00004c", "TeX": "#3D6117", "Textile": "#ffe7ac", "TextMate Properties": "#df66e4", "Thrift": "#D12127", "TI Program": "#A0AA87", "TLA": "#4b0079", "TOML": "#9c4221", "TSQL": "#e38c00", "TSV": "#237346", "TSX": "#3178c6", "Turing": "#cf142b", "Twig": "#c1d026", "TXL": "#0178b8", "TypeScript": "#3178c6", "Unified Parallel C": "#4e3617", "Unity3D Asset": "#222c37", "Unix Assembly": "#d2cece", "Uno": "#9933cc", "UnrealScript": "#a54c4d", "UrWeb": "#ccccee", "V": "#4f87c4", "Vala": "#a56de2", "Valve Data Format": "#f26025", "VBA": "#867db1", "VBScript": "#15dcdc", "VCL": "#148AA8", "Velocity Template Language": "#507cff", "Verilog": "#b2b7f8", "VHDL": "#adb2cb", "Vim Help File": "#199f4b", "Vim Script": "#199f4b", "Vim Snippet": "#199f4b", "Visual Basic .NET": "#945db7", "Visual Basic 6.0": "#2c6353", "Volt": "#1F1F1F", "Vue": "#41b883", "Vyper": "#2980b9", "wdl": "#42f1f4", "Web Ontology Language": "#5b70bd", "WebAssembly": "#04133b", "WebIDL": "#d2cece", "Whiley": "#d5c397", "Wikitext": "#fc5757", "Windows Registry Entries": "#52d5ff", "wisp": "#7582D1", "Witcher Script": "#ff0000", "Wollok": "#a23738", "World of Warcraft Addon Data": "#f7e43f", "Wren": "#383838", "X10": "#4B6BEF", "xBase": "#403a40", "XC": "#99DA07", "XML": "#0060ac", "XML Property List": "#0060ac", "Xojo": "#81bd41", "Xonsh": "#285EEF", "XProc": "#d2cece", "XQuery": "#5232e7", "XS": "#d2cece", "XSLT": "#EB8CEB", "Xtend": "#24255d", "Yacc": "#4B6C4B", "YAML": "#cb171e", "YARA": "#220000", "YASnippet": "#32AB90", "Yul": "#794932", "ZAP": "#0d665e", "Zeek": "#d2cece", "ZenScript": "#00BCD1", "Zephir": "#118f9e", "Zig": "#ec915c", "ZIL": "#dc75e5", "Zimpl": "#d67711"}

const totalPage = 40000

type GithubRepo struct {
	FullName    string `json:"full_name"`
	Name        string `json:"name"`
	Url         string `json:"html_url"`
	Stars       int    `json:"stargazers_count"`
	Description string `json:"description"`
	Owner       struct {
		AvatarUrl string `json:"avatar_url"`
		Login     string `json:"login"`
	} `json:"owner"`
	Language string `json:"language"`
}

type PopularRepo struct {
	User        string `json:"user"`
	Avatar      string `json:"avatar"`
	Repo        string `json:"repo"`
	Description string `json:"description"`
	Language    string `json:"language"`
	Color       string `json:"color"`
	Stars       int    `json:"stars"`
	Url         string `json:"url"`
}

func GetColor(lang any) string {
	if lang == nil {
		return "#d2cece"
	}
	val, ok := colors[lang.(string)]
	if !ok {
		return "#d2cece"
	}
	return val
}

func GetPopularRepo(page int) ([]PopularRepo, error) {
	if page*100 > totalPage {
		page = 1
	}

	uri := viper.GetString("github.endpoint") + "/search/repositories?q=stars:%3E1000&per_page=100&page=" + strconv.Itoa(page)
	data, err := Get(uri, map[string]string{
		"Accept":        "application/vnd.github.v3+json",
		"Authorization": "Bearer " + viper.GetString("github.token"),
	})

	if err != nil {
		return nil, err
	}

	var res []GithubRepo
	items := data.(map[string]interface{})["items"].([]interface{})

	err = MapToStruct(items, &res)
	if err != nil {
		return nil, err
	}

	return HandlePopularRepo(res), nil
}

func HandlePopularRepo(data []GithubRepo) []PopularRepo {
	var res []PopularRepo
	for _, v := range data {
		res = append(res, PopularRepo{
			User:        v.Owner.Login,
			Avatar:      v.Owner.AvatarUrl,
			Repo:        v.Name,
			Description: v.Description,
			Language:    v.Language,
			Stars:       v.Stars,
			Url:         v.Url,
			Color:       GetColor(v.Language),
		})
	}

	return res
}

func GetRandomPagination(data []PopularRepo) []PopularRepo {
	page := rand.Intn(25)
	return data[page*4 : page*4+4]
}

func GetRandomPopularRepoWithCache(ctx *gin.Context, cache *redis.Client) ([]PopularRepo, error) {
	page := rand.Intn(10)

	if result, err := cache.Get(ctx, fmt.Sprintf("popularepo:%d", page)).Result(); err == nil && result != "" {
		var res []PopularRepo
		if err = json.Unmarshal([]byte(result), &res); err == nil {
			return GetRandomPagination(res), nil
		}
	}

	res, err := GetPopularRepo(page)
	if err != nil {
		return nil, err
	}

	if buffer, err := json.Marshal(res); err == nil {
		cache.Set(ctx, fmt.Sprintf("popularepo:%d", page), buffer, time.Minute*2)
	}

	return GetRandomPagination(res), nil
}
